package com.example.glide.slice;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.target.BaseTarget;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.example.glide.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import com.bumptech.glide.Glide;
import com.example.glide.utils.LogUtil;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.aafwk.content.Intent;
import ohos.agp.render.*;
import ohos.agp.utils.RectFloat;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.media.image.ImagePacker;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.data.resultset.ResultSet;
import ohos.global.resource.NotExistException;
import ohos.media.common.sessioncore.*;
import ohos.media.photokit.metadata.AVStorage;
import ohos.utils.net.Uri;
import ohos.global.resource.*;
import ohos.agp.components.element.Element;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

import ohos.global.resource.ResourceManager;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import org.jetbrains.annotations.NotNull;

public class GlideAbilitySlice extends AbilitySlice {
    public Image imageview;
    public Image imageview2;
    public Image imageview3;
    public static final String urlstrig ="https://i.imgur.com/DvpvklR.png";

    // the media list got from the service
    private List<AVElement> avElementList = new ArrayList<>();
    private ComponentContainer mRootId;
    private Context classcontext;
    private static String TAG ="Glide";
    private static final int ID_BUTTON = 200;
    private static final int ID_BUTTON2 = 300;
    private static final int ID_BUTTON3 = 400;
    private static final int ID_BUTTON4 = 500;
    private static final int ID_BUTTON5 = 600;
    private static final int ID_BUTTON6 = 700;
    private static final int ID_BUTTON7 = 800;
    private static final int ID_BUTTON8 = 900;
    private static final int ID_BUTTON9 = 1000;
    private Button button, button2, button3, button4, button5, button6, button7, button8, button9;
    private AdaptiveBoxLayout myLayout = new AdaptiveBoxLayout(this);
    private TableLayout myLayout2 = new TableLayout(this);
    private ArrayList<String> data = new ArrayList<>();
    private AbilitySlice mSlice;
    private DataAbilityHelper helper ;
    private static final String DATAABILITY = "dataability";
    private static final String DATAABILITY_MEDIAIMAGES = "dataability:///media/external/images/media/";
    PixelMap myBitmap = null;
    byte[] bytes =null;

    DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(350, ComponentContainer.LayoutConfig.MATCH_CONTENT);

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        LogUtil.info(TAG, "onStart");
        LogUtil.info(TAG, "onStart");

        classcontext =getContext();
        String CONTENT = "dataability:///";
        String PKGNAME = classcontext.getBundleName();

        TableLayout tablelayout = new TableLayout(this);

        tablelayout.setColumnCount(3);
        tablelayout.setRowCount(3);
// Step 2 Set the layout size.
        tablelayout.setWidth(ComponentContainer.LayoutConfig.MATCH_CONTENT);
        tablelayout.setHeight(ComponentContainer.LayoutConfig.MATCH_CONTENT);
// Step 3 Set the layout attributes and ID (set the ID as required).
        tablelayout.setOrientation(Component.HORIZONTAL);

// Step 4.1 Add layout attributes for the control.
        //DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig(350, ComponentContainer.LayoutConfig.MATCH_CONTENT);

// Step 4.2 Add Text to the layout.
        //tablelayout.addComponent(text);
// Add all 9 buttons
        button = initButton();
        tablelayout.addComponent(button);
        button2 = initButton2();
        tablelayout.addComponent(button2);
        button3 = initButton3();
        tablelayout.addComponent(button3);
        button4 = initButton4();
        tablelayout.addComponent(button4);
        button5 = initButton5();
        tablelayout.addComponent(button5);
        button6 = initButton6();
        tablelayout.addComponent(button6);
        button7 = initButton7();
        tablelayout.addComponent(button7);
        button8 = initButton8();
        tablelayout.addComponent(button8);
        button9 = initButton9();
        tablelayout.addComponent(button9);

        DirectionalLayout verti_directionLayout = new DirectionalLayout(this);
// Step 2 Set the layout size.
        verti_directionLayout.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
        verti_directionLayout.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
// Step 3 Set the layout attributes and ID (set the ID as required).
        verti_directionLayout.setOrientation(Component.VERTICAL);

        //First add all the buttons then Imageviews
        verti_directionLayout.addComponent(tablelayout);

        //Create latyout config for Images
        DirectionalLayout.LayoutConfig imglayoutConfig = new DirectionalLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);

        imageview = new Image(this);
        imageview.setLayoutConfig(imglayoutConfig);
        imageview.setHeight(600);
        imageview.setPadding(10, 1, 10, 1);
        verti_directionLayout.addComponent(imageview);

        imageview2 = new Image(this);
        imageview2.setLayoutConfig(imglayoutConfig);
        imageview2.setHeight(600);
        imageview2.setPadding(10, 1, 10, 1);
        verti_directionLayout.addComponent(imageview2);

        imageview3 = new Image(this);
        imageview3.setLayoutConfig(imglayoutConfig);
        imageview3.setHeight(600);
        imageview3.setPadding(10, 1, 10, 1);
        verti_directionLayout.addComponent(imageview3);

        super.setUIContent(verti_directionLayout);
    }

    public PixelMap cropCircle(PixelMap bitmap) {

        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(bitmap.getImageInfo().size.width , bitmap.getImageInfo().size.height);
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        PixelMap output = PixelMap.create(initializationOptions);

        Canvas canvas = new Canvas(new Texture(output));

        final Paint paint = new Paint();
        final RectFloat rect = new RectFloat(0, 0, bitmap.getImageInfo().size.width , bitmap.getImageInfo().size.height);
        paint.setAntiAlias(true);
        canvas.drawCircle(bitmap.getImageInfo().size.width / 2, bitmap.getImageInfo().size.height / 2,
                bitmap.getImageInfo().size.width/2, paint);

        paint.setBlendMode(BlendMode.SRC_IN);
        canvas.drawPixelMapHolderRect( new PixelMapHolder(bitmap), rect , rect,  paint);
        return output;
    }

    private static Paint DEFAULT_PAINT = new Paint();
    private static final Paint CIRCLE_CROP_SHAPE_PAINT = new Paint();
    private static final Paint CIRCLE_CROP_BITMAP_PAINT = new Paint();

    static {
        try{
            DEFAULT_PAINT.setDither(true);
            DEFAULT_PAINT.setFilterBitmap(true);

            CIRCLE_CROP_SHAPE_PAINT.setDither(true);
            CIRCLE_CROP_SHAPE_PAINT.setFilterBitmap(true);
            CIRCLE_CROP_SHAPE_PAINT.setAntiAlias(true);

            CIRCLE_CROP_BITMAP_PAINT.setDither(true);
            CIRCLE_CROP_BITMAP_PAINT.setFilterBitmap(true);
            CIRCLE_CROP_BITMAP_PAINT.setAntiAlias(true);
            CIRCLE_CROP_BITMAP_PAINT.setBlendMode(BlendMode.SRC_IN);

        }
        catch(RuntimeException e){}
    }

    private PixelMap getAlphaSafeBitmap2(PixelMap maybeAlphaSafe) {
        PixelFormat safeConfig = PixelFormat.ARGB_8888;
        LogUtil.info(TAG, "Entering getAlphaSafeBitmap and PixelFormat is " + safeConfig);

        if (safeConfig.equals(maybeAlphaSafe.getImageInfo().pixelFormat)) {
            LogUtil.info(TAG, "Entering getAlphaSafeBitmap and return maybeAlphaSafe");
            return maybeAlphaSafe;
        }

        LogUtil.info(TAG, "Entering getAlphaSafeBitmap and width is " + maybeAlphaSafe.getImageInfo().size.width);
        LogUtil.info(TAG, "Entering getAlphaSafeBitmap and height is " + maybeAlphaSafe.getImageInfo().size.height);


        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = maybeAlphaSafe.getImageInfo().size;
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        PixelMap argbBitmap = PixelMap.create(initializationOptions);

        //new Canvas(new Texture(argbBitmap));

        return argbBitmap;
//
//        new Canvas(new Texture(argbBitmap)).drawPixelMapHolder( new PixelMapHolder(maybeAlphaSafe), 0 /*left*/, 0 /*top*/, null /*paint*/);
//
//
//        PixelMap.InitializationOptions initializationOptions2 = new PixelMap.InitializationOptions();
//        initializationOptions2.size = maybeAlphaSafe.getImageInfo().size;
//        initializationOptions2.pixelFormat = PixelFormat.ARGB_8888;
//        PixelMap result = PixelMap.create(initializationOptions2);
//
//        com.bumptech.glide.util.LogUtil.info(TAG, "Entering circleCrop and after getAlphaSafeBitmap()");
//
//        try {
//            Canvas canvas = new Canvas(new Texture(result));
//
//            // Draw a circle
//            float radius = maybeAlphaSafe.getImageInfo().size.width/2f;
//            canvas.drawCircle(radius, radius, radius, CIRCLE_CROP_SHAPE_PAINT);
//            // Draw the bitmap in the circle
//            //canvas.drawPixelMapHolderRect(new PixelMapHolder(argbBitmap), null, destRect, CIRCLE_CROP_BITMAP_PAINT);
//
//        } finally {
//        }
//
//        return result;

    }

    private Button initButton() {
        button = new Button(this);
        button.setLayoutConfig(layoutConfig);
        button.setText("Media Store");
        button.setTextSize(50);
        button.setId(ID_BUTTON);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button.setBackground(background);
        button.setPadding(10, 10, 10, 10);
        button.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from MediaStore");

                Uri uri =Uri.parse("dataability:///media/external/images/media/66");
                Glide.with(classcontext)
                        .load( uri)
                        .into(imageview);
            }
        });
        return button;
    }

    private Button initButton2() {
        button2 = new Button(this);
        button2.setLayoutConfig(layoutConfig);
        button2.setText("Drawable");
        button2.setTextSize(50);
        button2.setId(ID_BUTTON2);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button2.setBackground(background);
        button2.setPadding(10, 10, 10, 10);
        button2.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from Drawable folder");

                Glide.with(classcontext)
                        .load( ResourceTable.Media_desert)
                        .into(imageview);
            }
        });
        return button2;
    }


    private Button initButton3() {
        button3 = new Button(this);
        button3.setLayoutConfig(layoutConfig);
        button3.setText("Internet");
        button3.setTextSize(50);
        button3.setId(ID_BUTTON3);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button3.setBackground(background);
        button3.setPadding(10, 10, 10, 10);
        button3.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from Internet");

                Uri uri =Uri.parse(urlstrig);
                Glide.with(classcontext)
                        .load( uri)
                        .into(imageview);
            }
        });
        return button3;
    }

    private Button initButton4() {
        button4 = new Button(this);
        button4.setLayoutConfig(layoutConfig);
        button4.setText("Load Pixelmap");
        button4.setTextSize(50);
        button4.setId(ID_BUTTON4);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button4.setBackground(background);
        button4.setPadding(10, 10, 10, 10);
        button4.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from PixelMap");

                PixelMap pixelMap = getPixelMap(classcontext, ResourceTable.Media_jellyfish);
                Glide.with(classcontext)
                        .load( pixelMap)
                        .into(imageview);


            }
        });
        return button4;
    }

    private Button initButton5() {
        button5 = new Button(this);
        button5.setLayoutConfig(layoutConfig);
        button5.setText("GetBitmap");
        button5.setTextSize(50);
        button5.setId(ID_BUTTON5);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button5.setBackground(background);
        button5.setPadding(10, 10, 10, 10);
        button5.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from GetBitmap Thread");

                BackgroundThread m1=new BackgroundThread();
                Thread t1 =new Thread(m1);
                t1.start();
            }
        });
        return button5;
    }

    private Button initButton6() {
        button6 = new Button(this);
        button6.setLayoutConfig(layoutConfig);
        button6.setText("Get Byte[]");
        button6.setTextSize(50);
        button6.setId(ID_BUTTON6);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button6.setBackground(background);
        button6.setPadding(10, 10, 10, 10);
        button6.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from Get Byte[]");

                BackgroundThread3 m1=new BackgroundThread3();
                Thread t1 =new Thread(m1);
                t1.start();
            }
        });
        return button6;
    }

    private Button initButton7() {
        button7 = new Button(this);
        button7.setLayoutConfig(layoutConfig);
        button7.setText("Run Target");
        button7.setTextSize(50);
        button7.setId(ID_BUTTON7);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button7.setBackground(background);
        button7.setPadding(10, 10, 10, 10);
        button7.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from Target");

                Target<Element> target3 =
                        new Target<Element>() {
                            @Override
                            public void onStart() {

                            }

                            @Override
                            public void onStop() {

                            }

                            @Override
                            public void onDestroy() {

                            }

                            @Override
                            public void onLoadStarted( Element placeholder) {

                            }

                            @Override
                            public void onLoadFailed( Element errorDrawable) {

                            }


                            @Override
                            public void onResourceReady( Element bitmap, Transition<? super Element> transition) {
                                // do something with the bitmap
                                // for demonstration purposes, let's set it to an imageview
                                imageview.setImageElement( bitmap);
                            }


                            @Override
                            public void onLoadCleared( Element placeholder) {

                            }

                            @Override
                            public void getSize(SizeReadyCallback cb) {
                                cb.onSizeReady(850, 850);
                            }

                            @Override
                            public void removeCallback(SizeReadyCallback cb) {}


                            @Override
                            public void setRequest(Request request) {

                            }


                            @Override
                            public Request getRequest() {
                                return null;
                            }
                        };

                Glide.with(classcontext)
                        .load(ResourceTable.Media_tiger)
                        .into(target3);
            }
        });
        return button7;
    }

    private Button initButton8() {
        button8 = new Button(this);
        button8.setLayoutConfig(layoutConfig);
        button8.setText("BaseTarget");
        button8.setTextSize(50);
        button8.setId(ID_BUTTON8);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button8.setBackground(background);
        button8.setPadding(10, 10, 10, 10);
        button8.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from BaseTarget");

                BaseTarget<Element> target2 =
                        new BaseTarget<Element>() {
                            @Override
                            public void onResourceReady(
                                    Element bitmap, Transition<? super Element> transition) {
                                // do something with the bitmap
                                // for demonstration purposes, let's set it to an imageview
                                imageview.setImageElement( bitmap);
                            }

                            @Override
                            public void getSize(SizeReadyCallback cb) {
                                cb.onSizeReady(SIZE_ORIGINAL, SIZE_ORIGINAL);
                            }

                            @Override
                            public void removeCallback(SizeReadyCallback cb) {}
                        };

                Glide.with(classcontext)
                        .load(ResourceTable.Media_jellyfish)
                        .into(target2);
            }
        });
        return button8;
    }

    private Button initButton9() {
        button9 = new Button(this);
        button9.setLayoutConfig(layoutConfig);
        button9.setText("Media Store");
        button9.setTextSize(50);
        button9.setId(ID_BUTTON9);
        ShapeElement background = new ShapeElement();
        background.setRgbColor(RgbColor.fromArgbInt(Color.GREEN.getValue()));
        button9.setBackground(background);
        button9.setPadding(10, 10, 10, 10);
        button9.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component Component) {
                LogUtil.info(TAG, "loading from MediaStore");

                Uri uri =Uri.parse("dataability:///media/external/images/media/66");
                Glide.with(classcontext)
                        .load( uri)
                        .into(imageview);
            }
        });
        return button9;
    }


    class BackgroundThread implements Runnable{
        public void run(){
            try {

                myBitmap = Glide.with(classcontext)
                        .asBitmap()
                        .load(ResourceTable.Media_desert)
                        .into(500, 500)
                        .get();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(null != myBitmap){
                LogUtil.info(TAG, " TC Bitmap and bitmap is not null");
                TaskDispatcher dispatcher = classcontext.getUITaskDispatcher();
                dispatcher.asyncDispatch(new Runnable() {
                    @Override
                    public void run() {
                        imageview.setPixelMap( myBitmap);
                    }
                });
            }
            else
                LogUtil.info(TAG,"myBitmap null");
        }
    }

    class BackgroundThread3 implements Runnable{
        public void run(){
            try {
                bytes = Glide.with(classcontext)
                        .as(byte[].class)
                        .load(ResourceTable.Media_tiger)
                        .submit()
                        .get();

            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(null != bytes){
                LogUtil.info(TAG, "bytes not null and size is " + bytes.length);
            }
            else
                LogUtil.info(TAG, "bytes null");
        }
    }

    public static String getPathById(@NotNull Context context, int id) {
        String path = "";
        if (context == null) {
            LogUtil.error(TAG, "getPathById -> get null context");
            return path;
        }
        ResourceManager manager = context.getResourceManager();
        if (manager == null) {
            LogUtil.error(TAG, "getPathById -> get null ResourceManager");
            return path;
        }
        try {
            path = manager.getMediaPath(id);
        } catch (IOException e) {
            LogUtil.error(TAG, "getPathById -> IOException");
        } catch (NotExistException e) {
            LogUtil.error(TAG, "getPathById -> NotExistException");
        } catch (WrongTypeException e) {
            LogUtil.error(TAG, "getPathById -> WrongTypeException");
        }
        return path;
    }

    public static Optional<PixelMap> decodePixelMap(@NotNull Context context, int id) {
        String path = getPathById(context, id);
        RawFileEntry assetManager = context.getResourceManager().getRawFileEntry(path);
        ImageSource.SourceOptions options = new ImageSource.SourceOptions();
        options.formatHint = "image/png";
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        try {
            Resource asset = assetManager.openRawFile();
            ImageSource source = ImageSource.create(asset, options);
            return Optional.ofNullable(source.createPixelmap(decodingOptions));
        } catch (IOException e) {
            LogUtil.error(TAG, "getPixelMap -> IOException");
        }
        return Optional.empty();
    }

    public static PixelMap getPixelMap(@NotNull Context context, int resId) {
        Optional<PixelMap> optional = decodePixelMap(context, resId);
        return optional.get();
    }


    public static PixelMap createByResourceId(@NotNull Context context, int resourceId, String formatHint) throws IOException, NotExistException { if (context == null) { throw new IOException(); }
        ResourceManager manager = context.getResourceManager();
        if (manager == null) {
            throw new IOException();
        }
        ohos.global.resource.Resource resource = manager.getResource(resourceId); if (resource == null) { throw new IOException(); }
        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions(); srcOpts.formatHint = formatHint;
        ImageSource imageSource = null;
        try { imageSource = ImageSource.create(readResource(resource), srcOpts); } finally { close(resource); }
        if (imageSource == null) { throw new FileNotFoundException(); }
        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions(); decodingOpts.desiredSize = new Size(0, 0);
        decodingOpts.desiredRegion = new Rect(0, 0, 0, 0);
        decodingOpts.desiredPixelFormat = PixelFormat.ARGB_8888;
        PixelMap pixelmap = imageSource.createPixelmap(decodingOpts); return pixelmap;
    }

    private static void close(ohos.global.resource.Resource resource) {
        if (resource != null) {
            try {
                resource.close();
            }
            catch (IOException e) {
            }
        }
    }

    private static byte[] readResource(ohos.global.resource.Resource resource) {
        final int bufferSize = 1024;
        final int ioEnd = -1;
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[bufferSize];
        while (true) { try { int readLen = resource.read(buffer, 0, bufferSize);
            if (readLen == ioEnd) { break; }
            output.write(buffer, 0, readLen); } catch (IOException e) { break; } }
        return output.toByteArray();
    }


    public PixelMap getPixelMap() {
        PixelMap pixelMap =null;
        try{
            pixelMap = createByResourceId(classcontext, ResourceTable.Media_jellyfish, "image/png");

        }
        catch (IOException | NotExistException e) { }

        return pixelMap;
    }

    private void imageEncode(PixelMap pixelMap, OutputStream outputStream) {
        ImagePacker imagePacker = ImagePacker.create();
        ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
        packingOptions.format = "image/jpeg";
        packingOptions.quality = 100;
        packingOptions.numberHint = 1;
        boolean result = imagePacker.initializePacking(outputStream, packingOptions);
        imagePacker.addImage(pixelMap);
        imagePacker.finalizePacking();
        imagePacker.release();
    }

}
